package data.analysis.grammar;

import java.util.HashMap;
import java.util.Map;

import data.analysis.grammar.symbol.Scope;
import data.analysis.grammar.symbol.Symbol;

/**
 * Dictionary that maps from statistic script attribute access requests to Java target 
 * code strings.
 * @author Charles
 *
 */
public class OutputDictionary {
	public final Map<Path, Entry> map;
	
	/**
	 * Creates a new <code>OutputDictionary</code> with no mappings.
	 */
	public OutputDictionary() {
		this.map = new HashMap<Path, Entry>();
	}
	
	/**
	 * Creates a new mapping in this dictionary. The key of the new mapping will 
	 * be the attribute access of the specified symbol from the specified scope. 
	 * The value will be the set of Java target code strings defined by <b>type</b> 
	 * and <b>getter</b>.
	 * @param from the scope from which the attribute access request was made.
	 * @param to the symbol of the attribute being accessed.
	 * @param type the Java code string representing the data type of the attribute.
	 * @param getter the Java code string representing the method used to retrieve the 
	 * attribute.
	 * @return
	 */
	public Entry put(Scope from, Symbol to, String type, String getter) {
		Path p = new Path(from, to);
		return map.put(p, new Entry(type, getter));
	}
	
	/**
	 * Gets the entry associated with an attribute access.
	 * @param from the scope from which the attribute access request was made.
	 * @param to the symbol of the attribute being accessed.
	 * @return the {@link Entry} associated with the attribute access.
	 */
	public Entry get(Scope from, Symbol to) {
		return map.get(new Path(from, to));
	}
	
	/**
	 * Gets the entry associated with an attribute access represented by an 
	 * AST node.
	 * @param node the AST node representing the attribute access.
	 * @return the {@link Entry} associated with the attribute access.
	 */
	public Entry get(LocStatAST node) {
		return get(node.scope, node.symbol);
	}
	
	/**
	 * Wrapper class containing the <i>type</i> and <i>getter</i> strings for 
	 * an {@link OutputDictionary} mapping.
	 * @author Charles
	 *
	 */
	public class Entry {
		public final String type, getter;
		
		public Entry(String type, String getter) {
			this.type = type;
			this.getter = getter;
		}
	}
	
	private class Path {
		public final Scope from;
		public final Symbol to;
		
		public Path(Scope from, Symbol to) {
			this.from = from;
			this.to = to;
		}
		
		@Override
		public boolean equals(Object o) {
			if (o == null) {
				return false;
			}
			if (!o.getClass().equals(this.getClass())) {
				return false;
			}
			
			Path s = (Path)o;
			return s.from.equals(this.from) && s.to.equals(this.to);
		}
		
		@Override
		public int hashCode() {
			return from.hashCode() + to.hashCode();
		}
	}
}
